#include <iostream>
#include "handler.h"
#include "face_api_helper.h"
#include "return_json_object.h"
#include "face_container.h"
#include "log/logger.h"
#include "clock.h"
#include "exception.h"


shared_ptr<BaseObjectIf> handlerGetFaceAttr(const string& body)
{
	Clock clock("handlerGetFaceAttr");

	shared_ptr<RetFaceAttr> faceAttr(new RetFaceAttr(200,"success"));
	try {

		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");	
		} else {
			string img_base64;	
				
			if(!json_object["img"].isNull() && json_object["img"].isString()){
				img_base64 = json_object["img"].asString();
			} else {
				throw JsonFormatException("img error");
			}
			
			face_attr_t attr = FaceApiHelper::getInstance()->face_attr_by_base64(img_base64);
			faceAttr->setAttr(attr);
		}
	}
    catch( JsonFormatException& e) {
		faceAttr->setCode(400);
		faceAttr->setMessage(e.what());
	}
	catch( ApiReturnError& e)
	{
		faceAttr->setCode(500);
		faceAttr->setMessage(e.what());
	}
	
    
    return faceAttr;
}


shared_ptr<BaseObjectIf> handlerGetFaceQuality(const string& body)
{
	Clock clock("handlerGetFaceQuality");

	shared_ptr<RetFaceQuality> faceQuality(new RetFaceQuality(200,"success"));

	try {
		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");	
		} else {
			string img_base64;	
			
			if(!json_object["img"].isNull() && json_object["img"].isString()){
				img_base64 = json_object["img"].asString();
			} else {
				throw JsonFormatException("img error");
			}
			face_quality_t quality = FaceApiHelper::getInstance()->face_quality_by_base64(img_base64);
			faceQuality->setQuality(quality);
		}
	}
	catch( JsonFormatException& e) {
		faceQuality->setCode(400);
		faceQuality->setMessage(e.what());
	}
	catch(ApiReturnError& e) {
		faceQuality->setCode(500);
		faceQuality->setMessage(e.what());
	}


    return faceQuality;
}

void DumpTrackFaceInfo(const TrackFaceInfo& info)
{
	std::cout <<"face_id:" << info.face_id << std::endl;
	std::cout <<"score:" << info.score << std::endl;
	std::cout <<"box:" << std::endl;
	std::cout <<"   mWidth:" << info.box.mWidth << std::endl;
	std::cout <<"   mAngle:" << info.box.mAngle << std::endl;
	std::cout <<"   mCenter_x:"<< info.box.mCenter_x << std::endl;
	std::cout <<"   mCenter_y:"<< info.box.mCenter_y << std::endl;
	std::cout <<"   mConf:"<< info.box.mConf << std::endl;

	std::cout <<"landmarks:" << std::endl;
	for( uint32_t i = 0; i <info.landmarks.size(); i++){

		std::cout << "        " << info.landmarks[i] << std::endl;
	}
	std::cout <<"headPose:" << std::endl;
	for( uint32_t i = 0; i <info.headPose.size(); i++){

		std::cout << "        " << info.headPose[i] << std::endl;
	}

}


shared_ptr<BaseObjectIf> handlerGetFaceFeature(const string& body)
{
	Clock clock("handlerGetFaceFeature");

	shared_ptr<RetFaceFeature>  faceFeature(new RetFaceFeature(200,"success"));

	try{

		Json::Reader reader;
		Json::Value json_object;
		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");	

		} else {
			string img_base64;
			
			if(!json_object["img"].isNull() && json_object["img"].isString()){
				img_base64 = json_object["img"].asString();
			} else {
				throw JsonFormatException("img error");
			}

			std::vector<float> fs;
			int feature_num = FaceApiHelper::getInstance()->get_face_feature_by_base64(img_base64,fs);
			faceFeature->setFeature(fs);
		}

	}catch(JsonFormatException& e){
		faceFeature->setCode(400);
		faceFeature->setMessage(e.what());	
	}catch(ApiReturnError& e) {
		faceFeature->setCode(500);
		faceFeature->setMessage(e.what());
	}

    return faceFeature;
}


shared_ptr<BaseObjectIf> handlerMatchFaceByImg(const string& body)
{

	Clock clock("handlerMatchFaceByImg");

	shared_ptr<RetMatchFace> matchFace(new RetMatchFace(200,"success"));

	try{
		Json::Reader reader;
		Json::Value json_object;
		if (!reader.parse(body.c_str(), json_object)) {

			throw JsonFormatException("json format error");	
		} else {

			string img1_base64,img2_base64;
			if(!json_object["img1"].isNull() && json_object["img1"].isString()){
				img1_base64 = json_object["img1"].asString();
			} else {
				throw JsonFormatException("img1 error");
			}

			if(!json_object["img2"].isNull() && json_object["img2"].isString()){
				img2_base64 = json_object["img2"].asString();
			} else {
				throw JsonFormatException("img2 error");
			}
	
			float score = FaceApiHelper::getInstance()->match_by_base64(img1_base64,img2_base64);
			matchFace->setScore(score);
		}

	}catch(JsonFormatException& e){
		matchFace->setCode(400);
		matchFace->setMessage(e.what());	
	}catch(ApiReturnError& e) {
		matchFace->setCode(500);
		matchFace->setMessage(e.what());
	}

	return matchFace;
}


shared_ptr<BaseObjectIf> handlerRegisterFace(const string& body)
{
	Clock clock("handlerRegisterFace");

	shared_ptr<RetRegisterFace> regFace(new RetRegisterFace(200,"success"));

	try 
	{
		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");
			
		} else {
			string face_id;

			if(!json_object["faceId"].isNull()) {
				if(json_object["faceId"].isString()) {
					face_id = json_object["faceId"].asString();
				}else if( json_object["faceId"].isUInt()){
					face_id = to_string(json_object["faceId"].asUInt());
				}
			}else{
				throw JsonFormatException("faceId not exist");
			}

			string face_key;
			if(!json_object["faceKey"].isNull()) {
				if(json_object["faceKey"].isString()) {
					face_key = json_object["faceKey"].asString();
				}else if( json_object["faceKey"].isUInt()){
					face_key = to_string(json_object["faceKey"].asUInt());
				}
			}else{
				throw JsonFormatException("faceKey not exist");
			}

			string img_base64;
			if(!json_object["img"].isNull() && json_object["img"].isString()){
				img_base64 = json_object["img"].asString();
			} else {
				throw JsonFormatException("img error");
			}

			bool overrid = true;
			if( !json_object["override"].isNull() && json_object["override"].isBool()) {
				overrid = json_object["override"].asBool();
			}

			FaceContainer::getInstance()->AddFace(face_id,face_key,img_base64,overrid);
				
		}
	}catch(JsonFormatException& e){
		regFace->setCode(400);
		regFace->setMessage(e.what());	
	}catch(FaceContainerException& e){
		regFace->setCode(500);
		regFace->setMessage(e.what());
	}

	return regFace;
}


shared_ptr<BaseObjectIf> handlerSearchFace(const string& body)
{
	Clock clock("handlerSearchFace");

	shared_ptr<RetSearchFace> searchFace(new RetSearchFace(200,"success"));

	try 
	{
		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");
		} else {
	
			string img_base64;
			if( !json_object["img"].isNull() && json_object["img"].isString()){
				img_base64 = json_object["img"].asString();	
			}else{
				throw JsonFormatException("img error");
			}
			string face_id,face_key;
			float score = 0.000;
			FaceContainer::getInstance()->FindFace(img_base64,face_id,face_key,score);

			searchFace->setFaceId(face_id);
			searchFace->setScore(score);
			searchFace->setFaceKey(face_key);
		}
	}catch(JsonFormatException& e){
		searchFace->setCode(400);
		searchFace->setMessage(e.what());	

	}catch(FaceContainerException& e){
		searchFace->setCode(500);
		searchFace->setMessage(e.what());
	}

	return searchFace;

}


shared_ptr<BaseObjectIf> handlerMultSearchFace(const string& body)
{
	Clock clock("handlerMultSearchFace");

	shared_ptr<RetMultSearchFace> multSearchFace(new RetMultSearchFace(200,"success"));

	try 
	{
		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");
			
		} else {

			uint32_t img_num = 0;
			if( !json_object["imgNum"].isNull() && json_object["imgNum"].isUInt() ){
				img_num = json_object["imgNum"].asUInt();
			}else{
				throw JsonFormatException("imgNum error");
			}
			map<string,search_return_t> searched;
			for( uint32_t i = 0; i < img_num; i++ ){
				string imgName = "img" + to_string(i);

				string img_base64;
				if(!json_object[imgName].isNull() && json_object[imgName].isString()) {
					img_base64 = json_object[imgName].asString();	
				}else{
					throw JsonFormatException("img error");
				}

				string face_id,face_key;
				float score = 0.000;
				FaceContainer::getInstance()->FindFace(img_base64,face_id,face_key,score);

				search_return_t search_face;
				search_face.face_id = face_id;
				search_face.face_key = face_key;
				search_face.score = score;	
                search_face.img_name = imgName;
				searched[imgName] = search_face;
			}
			multSearchFace->setSearched(searched);
		}
	}catch(JsonFormatException& e){
		multSearchFace->setCode(400);
		multSearchFace->setMessage(e.what());	

	}catch(FaceContainerException& e){
		multSearchFace->setCode(500);
		multSearchFace->setMessage(e.what());
	}

	return multSearchFace;
}


shared_ptr<BaseObjectIf> handlerRemoveFace(const string& body)
{
	Clock clock("handlerRemoveFace");

	shared_ptr<RetRemoveFace> rmFace(new RetRemoveFace(200,"success"));

	try 
	{
		Json::Reader reader;
		Json::Value json_object;

		if (!reader.parse(body.c_str(), json_object)) {
			throw JsonFormatException("json format error");
		} else {

			string face_id;

			if(!json_object["faceId"].isNull()) {
				if(json_object["faceId"].isString()) {
					face_id = json_object["faceId"].asString();
				}else if( json_object["faceId"].isUInt()){
					face_id = to_string(json_object["faceId"].asUInt());
				}
			}else{
				throw JsonFormatException("faceId not exist");
			}
			
			FaceContainer::getInstance()->RemoveFace(face_id);
				
		}
		
	}catch(JsonFormatException& e){
		rmFace->setCode(400);
		rmFace->setMessage(e.what());	
	
	}catch(FaceContainerException& e){
		rmFace->setCode(500);
		rmFace->setMessage(e.what());
	}

	return rmFace;
}


shared_ptr<BaseObjectIf> handlerClearFaces(const string& body)
{
	Clock clock("handlerClearFaces");

	shared_ptr<RetClearFaces> clearFace(new RetClearFaces(200,"success"));

	try 
	{
		FaceContainer::getInstance()->ClearFace();
		
	}catch(FaceContainerException& e){
		clearFace->setCode(500);
		clearFace->setMessage(e.what());
	}

	return clearFace;
}

shared_ptr<BaseObjectIf> handlerNoHandler(const string& body)
{
	Clock clock("handlerNoHandler");

	shared_ptr<RetNoHandler> noHandler(new RetNoHandler(404,"no handler found"));
	
	return noHandler;
}

